PerlIO :APR / apr_file_open() flag issue

PerlIO :APR / apr_file_open() flag issue

am 21.04.2009 01:59:19 von Marc Adkins

This is a multi-part message in MIME format.
--------------030406030309040509030007
Content-Type: multipart/alternative;
boundary="------------080906040709040709080601"


--------------080906040709040709080601
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Originally posted to the APR dev list. The response (from jTrawick) was
as follows:

The Perl code that builds the apr_file_open() flags needs to turn on
APR_WRITE.

I think that this patch to mod_perl is what you need:

--- modperl_apr_perlio.c.orig 2007-12-31 02:39:50.000000000 -0500
+++ modperl_apr_perlio.c 2009-04-20 19:37:25.954107404 -0400
@@ -85,7 +85,7 @@

switch (*mode) {
case 'a':
- apr_flag = APR_APPEND | APR_CREATE;
+ apr_flag = APR_WRITE | APR_CREATE | APR_APPEND;
break;
case 'w':
apr_flag = APR_WRITE | APR_CREATE | APR_TRUNCATE;


The rest of this email is my original post. I would still like a
workaround is one exists.

------------------------------------------------------------ --

I found this in mod_perl but the issue can be demonstrated with Perl
alone and also without Perl. I'll start from the latter...

Attempting to open a file for append using the following flags:

APR_BUFFERED | APR_BINARY | APR_CREATE | APR_APPEND


will not work. The apr_file_open() function returns APR_EACCES. If the
following flags are used:

APR_BUFFERED | APR_BINARY | APR_CREATE | APR_WRITE | APR_APPEND


it works fine. In a vacuum this behavior is debatable. On the one
hand, APR_APPEND could be seen to imply APR_WRITE. On the other hand,
it might be argued that the first case is incomplete flag-wise.

In the context of Perl, however, particularly when using the APR PerlIO
filter, this becomes problematic. Perl uses special character sequences
which are converted to the proper flags down underneath the covers. So
in Perl '>' (write to a new file) converts properly but '>>' (append to
an existing file or create a new one if necessary) does not. There is
no message either, AFAIK, it just fails silently.

I'm attaching a couple of my test files. They demonstrate the problem
but don't show why it happens. I instrumented a copy of
file_io/unix/open.c to figure out what was happening. It fails in this
code:

if ((flag & APR_READ) && (flag & APR_WRITE)) {
oflags = O_RDWR;
}
else if (flag & APR_READ) {
oflags = O_RDONLY;
}
else if (flag & APR_WRITE) {
oflags = O_WRONLY;
}
else {
printf("fails here...\n");
return APR_EACCES;
}

I might suggest checking for APR_WRITE /or/ APR_APPEND, but there may be
some reason why it's done this way.

Has anyone else stumbled on this or am I doing something that breaks the
warranty? Is there a work-around in Perl?

--
Marc M. Adkins
Software Development Engineer
520 Pike Street, Suite 500
Seattle, WA 98101
P: 206-331-3508
F: 206.331.3695
E: madkins@marchex.com

Marchex Inc.
www.marchex.com

This e-mail message and any attachments are solely for
intended recipients, and may contain information that is
privileged and confidential. If you are not the intended
recipient, any dissemination, distribution or copying is
strictly prohibited. If you believe that you may have
received this message in error, please immediately notify
the sender by replying to this e-mail message.


--------------080906040709040709080601
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit






Originally posted to the APR dev list.  The response (from jTrawick)
was as follows:



The Perl code that builds the apr_file_open() flags needs
to turn on APR_WRITE.



I think that this patch to mod_perl is what you need:



---
modperl_apr_perlio.c.orig    2007-12-31 02:39:50.000000000 -0500

+++ modperl_apr_perlio.c    2009-04-20 19:37:25.954107404 -0400

@@ -85,7 +85,7 @@

 

     switch (*mode) {

       case 'a':

-        apr_flag = APR_APPEND | APR_CREATE;

+        apr_flag = APR_WRITE | APR_CREATE | APR_APPEND;

         break;

       case 'w':

         apr_flag = APR_WRITE | APR_CREATE | APR_TRUNCATE;





The rest of this email is my original post.  I would still like a
workaround is one exists.



------------------------------------------------------------ --



I found this in mod_perl but the issue can be demonstrated with Perl
alone and also without Perl.  I'll start from the latter...



Attempting to open a file for append using the following flags:



APR_BUFFERED |
APR_BINARY | APR_CREATE | APR_APPEND





will not work.  The apr_file_open()
function returns APR_EACCES
If the following flags are used:




APR_BUFFERED |
APR_BINARY | APR_CREATE | APR_WRITE | APR_APPEND





it works fine.  In a vacuum this behavior is debatable.  On the one
hand, APR_APPEND
could be seen to imply APR_WRITE
On the other hand, it might be argued that the first case is incomplete
flag-wise.



In the context of Perl, however, particularly when using the APR PerlIO
filter, this becomes problematic.  Perl uses special character
sequences which are converted to the proper flags down underneath the
covers.  So in Perl '>'
(write to a new file) converts properly but face="Courier New, Courier, monospace">'>>' (append to an
existing file or create a new one if necessary) does not.  There is no
message either, AFAIK, it just fails silently.



I'm attaching a couple of my test files.  They demonstrate the problem
but don't show why it happens.  I instrumented a copy of face="Courier New, Courier, monospace">file_io/unix/open.c to
figure out what was happening.  It fails in this code:



    if ((flag &
APR_READ) && (flag & APR_WRITE)) {

        oflags = O_RDWR;

    }

    else if (flag & APR_READ) {

        oflags = O_RDONLY;

    }

    else if (flag & APR_WRITE) {

        oflags = O_WRONLY;

    }

    else {

        printf("fails here...\n");

        return APR_EACCES;

    }



I might suggest checking for face="Courier New, Courier, monospace">APR_WRITE or face="Courier New, Courier, monospace">APR_APPEND, but there
may be some reason why it's done this way.



Has anyone else stumbled on this or am I doing something that breaks
the warranty?  Is there a work-around in Perl?



-- 
Marc M. Adkins
Software Development Engineer
520 Pike Street, Suite 500
Seattle, WA 98101
P: 206-331-3508
F: 206.331.3695
E:

Marchex Inc.


This e-mail message and any attachments are solely for
intended recipients, and may contain information that is
privileged and confidential. If you are not the intended
recipient, any dissemination, distribution or copying is
strictly prohibited. If you believe that you may have
received this message in error, please immediately notify
the sender by replying to this e-mail message.




--------------080906040709040709080601--

--------------030406030309040509030007
Content-Type: text/x-csrc;
name="aprio.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="aprio.c"


#include
#include

typedef long long off64_t;

#include
#include
#include

char *text = "Nevermore will we sing\n";

int main (int argc, const char *argv[]) {
apr_file_t *file;
apr_int32_t flag;
apr_pool_t *pool;
apr_size_t size;
apr_status_t stat;

stat = apr_initialize();

if (stat != APR_SUCCESS) {
printf("Unable to initialize\n");
return -1;
}

printf("Initialized!\n");

apr_pool_create(&pool, NULL);

// flag = APR_BUFFERED | APR_BINARY | APR_CREATE | APR_WRITE | APR_TRUNCATE;
flag = APR_BUFFERED | APR_BINARY | APR_CREATE | APR_APPEND;
// flag = APR_BUFFERED | APR_BINARY | APR_CREATE | APR_WRITE | APR_APPEND;
stat = apr_file_open(&file, "test.txt", flag, APR_OS_DEFAULT, pool);

if (stat == APR_SUCCESS) {
size = strlen(text);
stat = apr_file_write(file, text, &size);

if (stat != APR_SUCCESS) {
printf("Error writing to file (%d)\n", stat);
}
} else {
printf("Error opening file (%d)\n", stat);
}

apr_pool_destroy(pool);
apr_terminate();

return 0;
}



--------------030406030309040509030007
Content-Type: application/x-perl;
name="perlio-apr.pl"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="perlio-apr.pl"

#!/usr/bin/perl

use strict;
use warnings;

use APR::PerlIO;
use APR::Pool;

our $hndl;
our $pool = new APR::Pool;

warn "### $APR::PerlIO::VERSION\n";

die "*** Unable to open file: $! $@\n"
unless open $hndl, " >> :APR", "test.txt", $pool;

my @now = localtime;

printf $hndl "%04d-%02d-%02d %02d:%02d:%02d Testing, 1, 2, 3\n",
$now[5] + 1900, $now[4] + 1,
reverse @now[0..3];

close $hndl;



--------------030406030309040509030007--

Re: PerlIO :APR / apr_file_open() flag issue

am 21.04.2009 05:51:57 von gozer

This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
--------------enig6B8FC83D92D70BD3C70C883C
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

On 20/04/09 19:59 , Marc Adkins wrote:
> Originally posted to the APR dev list. The response (from jTrawick) wa=
s
> as follows:
>=20
> The Perl code that builds the apr_file_open() flags needs to turn o=
n
> APR_WRITE.
>=20
> I think that this patch to mod_perl is what you need:
>=20
> --- modperl_apr_perlio.c.orig 2007-12-31 02:39:50.000000000 -050=
0
> +++ modperl_apr_perlio.c 2009-04-20 19:37:25.954107404 -0400
> @@ -85,7 +85,7 @@
> =20
> switch (*mode) {
> case 'a':
> - apr_flag =3D APR_APPEND | APR_CREATE;
> + apr_flag =3D APR_WRITE | APR_CREATE | APR_APPEND;
> break;
> case 'w':
> apr_flag =3D APR_WRITE | APR_CREATE | APR_TRUNCATE;
>=20
>
> The rest of this email is my original post. I would still like a
> workaround is one exists.

Looks sensible to me. The only issue I could see is if APR_WRITE was
addeed at some point somewhat recently, and this change would break
against older APRs. Might need a version check of some sort.

Otherwise, +1

--=20
Philippe M. Chiasson GPG: F9BFE0C2480E7680 1AE53631CB32A107 88C3A5A5
http://gozer.ectoplasm.org/ m/gozer\@(apache|cpan|ectoplasm)\.org/


--------------enig6B8FC83D92D70BD3C70C883C
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (Darwin)

iD8DBQFJ7ULeyzKhB4jDpaURAtsbAJoCCtdN5BM4J1/J7eq7dyeeuK5sjACe KPNs
48lWAhn1fiXmjMDCepb8UZU=
=Szii
-----END PGP SIGNATURE-----

--------------enig6B8FC83D92D70BD3C70C883C--

Re: PerlIO :APR / apr_file_open() flag issue

am 22.04.2009 17:19:55 von Marc Adkins

This is a multi-part message in MIME format.
--------------040301030807000008000102
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

So are there no work-arounds for this? I notice that there seems to be
only the PerlIO interface to the APR file I/O functionality. If there
was a more direct Perl API (wherein I could pass the flags I want) this
wouldn't be an issue.

Philippe M. Chiasson wrote:
> On 20/04/09 19:59 , Marc Adkins wrote:
>
>> Originally posted to the APR dev list. The response (from jTrawick) was
>> as follows:
>>
>> The Perl code that builds the apr_file_open() flags needs to turn on
>> APR_WRITE.
>>
>> I think that this patch to mod_perl is what you need:
>>
>> --- modperl_apr_perlio.c.orig 2007-12-31 02:39:50.000000000 -0500
>> +++ modperl_apr_perlio.c 2009-04-20 19:37:25.954107404 -0400
>> @@ -85,7 +85,7 @@
>>
>> switch (*mode) {
>> case 'a':
>> - apr_flag = APR_APPEND | APR_CREATE;
>> + apr_flag = APR_WRITE | APR_CREATE | APR_APPEND;
>> break;
>> case 'w':
>> apr_flag = APR_WRITE | APR_CREATE | APR_TRUNCATE;
>>
>>
>> The rest of this email is my original post. I would still like a
>> workaround is one exists.
>>
>
> Looks sensible to me. The only issue I could see is if APR_WRITE was
> addeed at some point somewhat recently, and this change would break
> against older APRs. Might need a version check of some sort.
>
> Otherwise, +1
>
>


--
Marc M. Adkins
Software Development Engineer
520 Pike Street, Suite 500
Seattle, WA 98101
P: 206-331-3508
F: 206.331.3695
E: madkins@marchex.com

Marchex Inc.
www.marchex.com

This e-mail message and any attachments are solely for
intended recipients, and may contain information that is
privileged and confidential. If you are not the intended
recipient, any dissemination, distribution or copying is
strictly prohibited. If you believe that you may have
received this message in error, please immediately notify
the sender by replying to this e-mail message.


--------------040301030807000008000102
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit







So are there no work-arounds for this?  I notice that there seems to be
only the PerlIO interface to the APR file I/O functionality.  If there
was a more direct Perl API (wherein I could pass the flags I want) this
wouldn't be an issue.



Philippe M. Chiasson wrote:


On 20/04/09 19:59 , Marc Adkins wrote:


Originally posted to the APR dev list.  The response (from jTrawick) was
as follows:

The Perl code that builds the apr_file_open() flags needs to turn on
APR_WRITE.

I think that this patch to mod_perl is what you need:

--- modperl_apr_perlio.c.orig 2007-12-31 02:39:50.000000000 -0500
+++ modperl_apr_perlio.c 2009-04-20 19:37:25.954107404 -0400
@@ -85,7 +85,7 @@

switch (*mode) {
case 'a':
- apr_flag = APR_APPEND | APR_CREATE;
+ apr_flag = APR_WRITE | APR_CREATE | APR_APPEND;
break;
case 'w':
apr_flag = APR_WRITE | APR_CREATE | APR_TRUNCATE;


The rest of this email is my original post. I would still like a
workaround is one exists.



Looks sensible to me. The only issue I could see is if APR_WRITE was
addeed at some point somewhat recently, and this change would break
against older APRs. Might need a version check of some sort.

Otherwise, +1







-- 
Marc M. Adkins
Software Development Engineer
520 Pike Street, Suite 500
Seattle, WA 98101
P: 206-331-3508
F: 206.331.3695
E:

Marchex Inc.


This e-mail message and any attachments are solely for
intended recipients, and may contain information that is
privileged and confidential. If you are not the intended
recipient, any dissemination, distribution or copying is
strictly prohibited. If you believe that you may have
received this message in error, please immediately notify
the sender by replying to this e-mail message.




--------------040301030807000008000102--

Re: PerlIO :APR / apr_file_open() flag issue

am 25.04.2009 16:04:30 von Jeff Trawick

--000e0cd247508cff76046861977a
Content-Type: multipart/alternative; boundary=000e0cd247508cff600468619778

--000e0cd247508cff600468619778
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

>The only issue I could see is if APR_WRITE was addeed
>at some point somewhat recently, and this change would break
>against older APRs.

APR_READ and/or APR_WRITE has been required since the first APR release.
Here's the logic to check for APR_READ/APR_WRITE back in 1999 (still called
"ap_open" at that point):

(
http://svn.apache.org/viewvc/apr/apr/branches/0.9.x/file_io/ unix/open.c?revision=59512&view=markup
)

*if* ((flag & APR_READ) && (flag & APR_WRITE)) {

}
*else* *if* (flag & APR_READ) {

}
*else* *if* (flag & APR_WRITE) {

}
*else* {
*return* APR_EACCES;
}



---------- Forwarded message ----------
From: "Philippe M. Chiasson"
To: Marc Adkins
Date: Mon, 20 Apr 2009 23:51:57 -0400
Subject: Re: PerlIO :APR / apr_file_open() flag issue
On 20/04/09 19:59 , Marc Adkins wrote:
> Originally posted to the APR dev list. The response (from jTrawick) was
> as follows:
>
> The Perl code that builds the apr_file_open() flags needs to turn on
> APR_WRITE.
>
> I think that this patch to mod_perl is what you need:
>
> --- modperl_apr_perlio.c.orig 2007-12-31 02:39:50.000000000 -0500
> +++ modperl_apr_perlio.c 2009-04-20 19:37:25.954107404 -0400
> @@ -85,7 +85,7 @@
>
> switch (*mode) {
> case 'a':
> - apr_flag = APR_APPEND | APR_CREATE;
> + apr_flag = APR_WRITE | APR_CREATE | APR_APPEND;
> break;
> case 'w':
> apr_flag = APR_WRITE | APR_CREATE | APR_TRUNCATE;
>
>
> The rest of this email is my original post. I would still like a
> workaround is one exists.

Looks sensible to me. The only issue I could see is if APR_WRITE was
addeed at some point somewhat recently, and this change would break
against older APRs. Might need a version check of some sort.

Otherwise, +1

--000e0cd247508cff600468619778
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

>The only issue I could see is if APR_WRITE w=
as addeed
>at some point somewhat recently, and this change would bre=
ak
>against older APRs.

APR_READ and/or APR_WRITE has been req=
uired since the first APR release.=A0 Here's the logic to check for APR=
_READ/APR_WRITE back in 1999 (still called "ap_open" at that poin=
t):


( /unix/open.c?revision=3D59512&view=3Dmarkup">http://svn. apache.org/view=
vc/apr/apr/branches/0.9.x/file_io/unix/open.c?revision=3D595 12&view=3Dm=
arkup
)


if ((flag & APR_REA=
D) && (flag & APR_WRITE)) {

}
f0">else if (flag & AP=
R_READ) {


}
else f0">if (flag & APR_WRITE) {

}
020f0">else {
return > APR_EACCES;

}


---------- Forwarded message ----------
From:=
=A0"Philippe M. Chiasson" < >gozer@apache.org>
To:=A0Marc Adkins < s@marchex.com">madkins@marchex.com>

Date:=A0Mon, 20 Apr 2009 23:51:57 -0400
Subject:=A0Re: PerlIO :APR / apr=
_file_open() flag issue
On 20/04/09 19:59 , Marc Adkins wrote:

> Originally posted to the APR dev list. =A0The response (from jTrawick)=
was

> as follows:

>

> =A0 =A0 The Perl code that builds the apr_file_open() flags needs to t=
urn on

> =A0 =A0 APR_WRITE.

>

> =A0 =A0 I think that this patch to mod_perl is what you need:

>

> =A0 =A0 --- modperl_apr_perlio.c.orig =A0 =A02007-12-31 02:39:50.00000=
0000 -0500

> =A0 =A0 +++ modperl_apr_perlio.c =A0 =A02009-04-20 19:37:25.954107404 =
-0400

> =A0 =A0 @@ -85,7 +85,7 @@

>

> =A0 =A0 =A0 =A0 =A0switch (*mode) {

> =A0 =A0 =A0 =A0 =A0 =A0case 'a':

> =A0 =A0 - =A0 =A0 =A0 =A0apr_flag =3D APR_APPEND | APR_CREATE;

> =A0 =A0 + =A0 =A0 =A0 =A0apr_flag =3D APR_WRITE | APR_CREATE | APR_APP=
END;

> =A0 =A0 =A0 =A0 =A0 =A0 =A0break;

> =A0 =A0 =A0 =A0 =A0 =A0case 'w':

> =A0 =A0 =A0 =A0 =A0 =A0 =A0apr_flag =3D APR_WRITE | APR_CREATE | APR_T=
RUNCATE;

>

>

> The rest of this email is my original post. =A0I would still like a >
> workaround is one exists.



Looks sensible to me. The only issue I could see is if APR_WRITE was

addeed at some point somewhat recently, and this change would break

against older APRs. Might need a version check of some sort.



Otherwise, +1






--000e0cd247508cff600468619778--
--000e0cd247508cff76046861977a
Content-Type: application/pgp-signature; name="signature.asc"
Content-Disposition: attachment; filename="signature.asc"
Content-Transfer-Encoding: base64
X-Attachment-Id: 0.1.0.1

LS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJFLS0tLS0KVmVyc2lvbjogR251UEcg djEuNC43IChEYXJ3
aW4pCgppRDhEQlFGSjdVTGV5ektoQjRqRHBhVVJBdHNiQUpvQ0N0ZE41Qk00 SjEvSjdlcTdkeWVl
dUs1c2pBQ2VLUE5zCjQ4bFdBaG4xZmlYbWpNRENlcGI4VVpVPQo9U3ppaQot LS0tLUVORCBQR1Ag
U0lHTkFUVVJFLS0tLS0K
--000e0cd247508cff76046861977a--